/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop;

import org.aopalliance.intercept.MethodInvocation;

import org.springframework.lang.Nullable;

/**
 * AOP联盟{@link org.aopalliance.intercept.MethodInvocation}的扩展。
 * 接口的扩展，允许访问方法调用所通过的代理。
 *
 * 能够用代理来替代返回值是很有用的。
 * 如果有必要的话，例如，如果调用目标返回自己。
 *
 * @author Juergen Hoeller
 * @author Adrian Colyer
 * @since 1.1.3
 * @see org.springframework.aop.framework.ReflectiveMethodInvocation
 * @see org.springframework.aop.support.DelegatingIntroductionInterceptor
 */
public interface ProxyMethodInvocation extends MethodInvocation {

	/**
	 * 返回这个方法的调用是通过代理进行的。
	 * @return 原始代理对象
	 */
	Object getProxy();

	/**
	 * 创建一个此对象的克隆。如果克隆是在{@code proceed()}之前完成的，
	 * 那么在这个对象上调用{@code proceed()}时之前进行克隆，则每个克隆对象可以调用一次{@code proceed()}。
	 * 来多次调用连接点（以及建议链的其他部分）。
	 * @return 该调用的一个可调用的克隆。
	 * 			{@code proceed()}在每个克隆中可以被调用一次。
	 */
	MethodInvocation invocableClone();

	/**
	 * 创建一个此对象的克隆。如果克隆是在{@code proceed()}之前完成的，
	 * 那么在这个对象上调用{@code proceed()}时之前进行克隆，则每个克隆对象可以调用一次{@code proceed()}。
	 * 来多次调用连接点（以及建议链的其他部分）。
	 * @param arguments 克隆的调用应该使用的参数。凌驾于原始参数之上
	 * @return 该调用的一个可调用的克隆。
	 *            {@code proceed()}在每个克隆中可以被调用一次。
	 */
	MethodInvocation invocableClone(Object... arguments);

	/**
	 * 设置在后续调用中使用的参数中的参数。
	 * @param arguments 参数数组
	 */
	void setArguments(Object... arguments);

	/**
	 *
	 *
	 */
	/**
	 * 将指定的用户属性以给定的值添加到这个调用中。
	 * 这种属性并不在AOP框架本身中使用。
	 * 它们是只是作为调用对象的一部分被保留下来，以便在特殊的拦截器中使用。
	 * @param key
	 * @param value 属性的值，或者用{@code null}来重置它。
	 */
	void setUserAttribute(String key, @Nullable Object value);

	/**
	 * 返回指定的用户属性的值。
	 * @param key 属性的名称
	 * @return 该属性的值，如果没有设置，则为{@code null}。
	 * @see #setUserAttribute
	 */
	@Nullable
	Object getUserAttribute(String key);

}
